# 导入装饰器
from typing import Any, Callable, Optional, TypeVar

F = TypeVar("F", bound=Callable[..., Any])


def test(
    test_case: str = "DefaultTest", test_name: Optional[str] = None
) -> Callable[[F], F]:
    """GTest 测试用例装饰器

    用于标记一个函数为 GTest 测试用例，生成 TEST(test_case, test_name) 宏。

    Args:
        test_case: 测试用例名称，默认为 "DefaultTest"
        test_name: 测试名称，默认使用函数名

    Returns:
        装饰器函数

    Example:
        @test("MathTest", "Addition")
        def test_addition():
            EXPECT_EQ(1 + 1, 2)
    """

    def decorator(func: F) -> F:
        # 在编译时，这个装饰器会被 gtest_extensions.py 处理
        # 运行时不做任何处理，直接返回原函数
        return func

    return decorator


def fixture(fixture_name: Optional[str] = None) -> Callable[[type], type]:
    """GTest 测试夹具装饰器

    用于标记一个类为 GTest 测试夹具，继承自 ::testing::Test。

    Args:
        fixture_name: 夹具名称，默认使用类名

    Returns:
        装饰器函数

    Example:
        @fixture()
        class MathFixture:
            def setUp(self):
                self.calculator = Calculator()
    """

    def decorator(cls: type) -> type:
        # 在编译时，这个装饰器会被 gtest_extensions.py 处理
        # 运行时不做任何处理，直接返回原类
        return cls

    return decorator


def test_f(fixture_class: str, test_name: Optional[str] = None) -> Callable[[F], F]:
    """GTest 夹具测试用例装饰器

    用于标记一个函数为基于夹具的 GTest 测试用例，生成 TEST_F(fixture_class, test_name) 宏。

    Args:
        fixture_class: 夹具类名
        test_name: 测试名称，默认使用函数名

    Returns:
        装饰器函数

    Example:
        @test_f("MathFixture", "Addition")
        def test_addition():
            EXPECT_EQ(self.calculator.add(1, 1), 2)
    """

    def decorator(func: F) -> F:
        # 在编译时，这个装饰器会被 gtest_extensions.py 处理
        # 运行时不做任何处理，直接返回原函数
        return func

    return decorator
